package utils

import (
	"errors"
	"fmt"
	"time"
	"wms/config"

	"github.com/golang-jwt/jwt/v5"
)

// JWTConfig JWT配置
type JWTConfig struct {
	SecretKey string // 密钥
	ExpiresIn int    // 过期时间（小时）
	Issuer    string // 签发者
}

// DefaultJWTConfig 默认JWT配置
var DefaultJWTConfig = JWTConfig{
	SecretKey: "wms-secret-key",
	ExpiresIn: 24,
	Issuer:    "wms",
}

// Claims 自定义JWT声明
type Claims struct {
	UserID   uint   `json:"user_id"`
	Username string `json:"username"`
	RoleID   uint   `json:"role_id"`
	jwt.RegisteredClaims
}

// GetJWTSecretKey 获取JWT密钥
func GetJWTSecretKey() string {
	// 从配置文件获取密钥
	secret := config.GetConfig().JWT.Secret

	// 如果配置中的密钥为空，则使用默认密钥
	if secret == "" {
		return DefaultJWTConfig.SecretKey
	}

	return secret
}

// GetJWTExpiresIn 获取JWT过期时间（秒）
func GetJWTExpiresIn() int {
	return config.GetConfig().JWT.ExpiresIn
}

// GenerateToken 生成Token
func GenerateToken(userID uint, username string, roleID uint) (string, error) {
	expiresIn := GetJWTExpiresIn()
	if expiresIn <= 0 {
		expiresIn = 86400 // 默认24小时
	}

	claims := Claims{
		UserID:   userID,
		Username: username,
		RoleID:   roleID,
		RegisteredClaims: jwt.RegisteredClaims{
			ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Second * time.Duration(expiresIn))),
			IssuedAt:  jwt.NewNumericDate(time.Now()),
			NotBefore: jwt.NewNumericDate(time.Now()),
			Issuer:    "wms",
		},
	}

	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	return token.SignedString([]byte(GetJWTSecretKey()))
}

// ParseToken 解析Token
func ParseToken(tokenString string) (*Claims, error) {
	// 打印用于验证的密钥，帮助调试
	secretKey := GetJWTSecretKey()

	// 安全获取前几个字符用于调试
	tokenPrefix := ""
	if len(tokenString) > 10 {
		tokenPrefix = tokenString[:10]
	} else if len(tokenString) > 0 {
		tokenPrefix = tokenString
	}

	secretKeyPrefix := ""
	if len(secretKey) > 3 {
		secretKeyPrefix = secretKey[:3]
	} else if len(secretKey) > 0 {
		secretKeyPrefix = secretKey
	}

	fmt.Printf("开始解析Token: token前缀=%s..., secretKey前缀=%s...\n",
		tokenPrefix, secretKeyPrefix)

	// 尝试解析token
	token, err := jwt.ParseWithClaims(tokenString, &Claims{}, func(token *jwt.Token) (interface{}, error) {
		// 检查签名方法
		if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
			errMsg := fmt.Sprintf("unexpected signing method: %v", token.Header["alg"])
			fmt.Printf("签名方法不匹配: %s\n", errMsg)
			return nil, fmt.Errorf("%s", errMsg)
		}
		return []byte(secretKey), nil
	})

	// 处理解析错误
	if err != nil {
		fmt.Printf("Token解析失败: 错误=%v\n", err)
		return nil, err
	}

	// 验证claims类型和有效性
	if claims, ok := token.Claims.(*Claims); ok && token.Valid {
		fmt.Printf("Token验证成功: userID=%d, username=%s\n",
			claims.UserID, claims.Username)
		return claims, nil
	}

	fmt.Printf("Token无效\n")
	return nil, errors.New("无效的Token")
}
